package com.uiotsoft.small.sampler;

import com.uiotsoft.small.config.APPConfig;
import com.uiotsoft.small.mqtt.MqttClientOld;
import com.uiotsoft.util.encrypt.MD5Utils;
import com.uiotsoft.util.encrypt.small.SignUtil;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.JMeterVariables;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MqttConnectSampler extends AbstractJavaSamplerClient {
    private volatile MqttClientOld clientOld;
    private static final Logger log = LoggerFactory.getLogger(MqttConnectSampler.class);
    private String subTopic;
    private MqttConnectOptions options;

    public Arguments getDefaultParameters() {
        Arguments params = new Arguments();
        params.addArgument("type", "app/host");
        params.addArgument("appKey", "${appKey}");
        params.addArgument("appSecret", "${appSecret}");
        params.addArgument("mqttUrl", "${mqttUrl}");
        params.addArgument("username", "${appKey}|${sn}|host|${__time(/1000,)}");
        params.addArgument("clientId", "host-${sn}/uiot_app-${si}");
        params.addArgument("subTopic", "host/+/+/${sn}/+");
        params.addArgument("willTopic", "");
        params.addArgument("willData", "");
        return params;
    }

    private void setupValues(JavaSamplerContext context) {
        String appKey = context.getParameter("appKey");
        String appSecret = context.getParameter("appSecret");
        String mqttUrl = context.getParameter("mqttUrl");
        String username = context.getParameter("username");
        String clientId = context.getParameter("clientId");
        subTopic = context.getParameter("subTopic");
        String willTopic = context.getParameter("willTopic");
        String willData = context.getParameter("willData");
        String password_new = MD5Utils.MD5Encoding(username + appSecret, "");
        clientOld = new MqttClientOld(mqttUrl, clientId);
        clientOld.setAppKey(appKey);
        clientOld.setAppSecret(appSecret);
        options = new MqttConnectOptions();
        options.setMqttVersion(3);
        options.setConnectionTimeout(10);
        options.setMaxReconnectDelay(5);
        options.setKeepAliveInterval(30);
        options.setCleanSession(false);
        options.setAutomaticReconnect(true);
        options.setUserName(username);
        options.setPassword(password_new.toCharArray());
        //设置遗嘱
        if (willTopic != null && !willTopic.equals("")){
            if (appSecret != null && !appSecret.equals("")){
                byte[] message = SignUtil.getPublishMessage(willData, APPConfig.CHK_appKey,APPConfig.CHK_appSecret);
                options.setWill(willTopic, message, 0, true);
            }else {
                log.error("appsecret 为空！");
            }
        }
    }

    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
        setupValues(javaSamplerContext);
        String type = javaSamplerContext.getParameter("type");
        JMeterVariables vars = JMeterContextService.getContext().getVariables();
        SampleResult results = new SampleResult();
        results.sampleStart();
        try {
            clientOld.setMqttClient(options, null);
            clientOld.subscribe(subTopic);
            if (clientOld.getMqttClient().isConnected()){
                log.info("Connected client: "+clientOld.getClientId());
                if (type.toLowerCase().startsWith("app")){
                    if (type.toLowerCase().contains("local")){
                        vars.putObject("appLocalMqttClient", clientOld);
                    }else {
                        vars.putObject("appMqttClient", clientOld);
                    }
                }else if (type.toLowerCase().startsWith("host")){
                    vars.putObject("hostMqttClient", clientOld);
                }
                results.setSuccessful(true);
                results.setResponseData("Successful", "UTF-8");
                results.setResponseMessage("Connection established successfully.");
                results.setResponseCodeOK();
            }else {
                results.setSuccessful(false);
                results.setResponseData("Connect failed", "UTF-8");
                results.setResponseMessage("Failed to establish Connection.");
                results.setResponseCode("501");
            }
        } catch (MqttException e) {
            if (results.getEndTime() == 0) results.sampleEnd();
            log.info("Failed to establish Connection :{}", e.getMessage());
            results.setSuccessful(false);
            results.setResponseData("Connect failed with exception", "UTF-8");
            results.setResponseMessage("Failed to establish Connection.");
            results.setResponseCode("502");
        }
        results.sampleEnd();
        return results;
    }

}
